<template>
    <div>
        <div v-if="searchable && searchPlace === 'top'" class="search-con search-con-top">
            <Select v-model="searchKey" class="search-col">
                <Option v-for="item in columns"
                        v-if="item.type !== 'handle' && item.type!=='index' && item.key!=='action'"
                        :value="item.key"
                        :key="`search-col-${item.key}`">
                    {{ item.title }}
                </Option>
            </Select>
            <Input @on-change="handleClear" clearable placeholder="输入关键字搜索" class="search-input" v-model="searchValue"/>
            <Button @click="handleSearch" class="search-btn" type="primary">
                <Icon type="search"/>&nbsp;&nbsp;搜索
            </Button>
        </div>
        <Table
                ref="tablesMain"
                :data="insideTableData"
                :columns="insideColumns"
                :stripe="stripe"
                :border="border"
                :show-header="showHeader"
                :width="width"
                :height="height"
                :loading="loading"
                :disabled-hover="disabledHover"
                :highlight-row="highlightRow"
                :row-class-name="rowClassName"
                :size="size"
                :no-data-text="noDataText"
                :no-filtered-data-text="noFilteredDataText"
                @on-current-change="onCurrentChange"
                @on-select="onSelect"
                @on-select-cancel="onSelectCancel"
                @on-select-all="onSelectAll"
                @on-selection-change="onSelectionChange"
                @on-sort-change="onSortChange"
                @on-filter-change="onFilterChange"
                @on-row-click="onRowClick"
                @on-row-dblclick="onRowDblclick"
                @on-expand="onExpand"
        >
            <slot name="header" slot="header"></slot>
            <slot name="footer" slot="footer"></slot>
            <slot name="loading" slot="loading"></slot>
        </Table>
        <div v-if="searchable && searchPlace === 'bottom'" class="search-con search-con-top">
            <Select v-model="searchKey" class="search-col">
                <Option v-for="item in columns"
                        v-if="item.type !== 'index' && item.type!=='selection'"
                        :value="item.key"
                        :key="`search-col-${item.key}`">
                    {{ item.title }}
                </Option>
            </Select>
            <Input placeholder="输入关键字搜索" class="search-input" v-model="searchValue"/>
            <Button class="search-btn" type="primary">
                <Icon type="search"/>&nbsp;&nbsp;搜索
            </Button>
        </div>
        <a id="hrefToExportTable" style="display: none;width: 0px;height: 0px;"></a>
    </div>
</template>

<script>
    import TablesEdit from './edit.vue';
    import handleBtns from './handle-btns';
    import Enumerable from 'linq';

    export default {
        name: 'Tables',
        props: {
            value: {
                type: Array,
                default() {
                    return [];
                }
            },
            columns: {
                type: Array,
                default() {
                    return [];
                }
            },
            size: String,
            width: {
                type: [Number, String]
            },
            height: {
                type: [Number, String]
            },
            stripe: {
                type: Boolean,
                default: false
            },
            border: {
                type: Boolean,
                default: false
            },
            showHeader: {
                type: Boolean,
                default: true
            },
            highlightRow: {
                type: Boolean,
                default: false
            },
            rowClassName: {
                type: Function,
                default() {
                    return '';
                }
            },
            context: {
                type: Object
            },
            noDataText: {
                type: String
            },
            noFilteredDataText: {
                type: String
            },
            disabledHover: {
                type: Boolean
            },
            loading: {
                type: Boolean,
                default: false
            },
            /**
             * @description 全局设置是否可编辑
             */
            editable: {
                type: Boolean,
                default: false
            },
            /**
             * @description 是否可搜索
             */
            searchable: {
                type: Boolean,
                default: false
            },
            /**
             * @description 搜索控件所在位置，'top' / 'bottom'
             */
            searchPlace: {
                type: String,
                default: 'top'
            }
        },
        /**
         * Events
         * @on-start-edit 返回值 {Object} ：同iview中render函数中的params对象 { row, index, column }
         * @on-cancel-edit 返回值 {Object} 同上
         * @on-save-edit 返回值 {Object} ：除上面三个参数外，还有一个value: 修改后的数据
         */
        data() {
            return {
                insideColumns: [],
                insideTableData: [],
                edittingCellId: '',
                edittingText: '',
                searchValue: '',
                searchKey: ''
            };
        },
        methods: {
            suportEdit(item, index) {
                item.render = (h, params) => {
                    return h(TablesEdit, {
                        props: {
                            params: params,
                            value: this.insideTableData[params.index][params.column.key],
                            edittingCellId: this.edittingCellId,
                            editable: this.editable
                        },
                        on: {
                            'input': val => {
                                this.edittingText = val;
                            },
                            'on-start-edit': (params) => {
                                this.edittingCellId = `editting-${params.index}-${params.column.key}`;
                                this.$emit('on-start-edit', params);
                            },
                            'on-cancel-edit': (params) => {
                                this.edittingCellId = '';
                                this.$emit('on-cancel-edit', params);
                            },
                            'on-save-edit': (params) => {
                                this.value[params.index][params.column.key] = this.edittingText;
                                this.$emit('input', this.value);
                                this.$emit('on-save-edit', Object.assign(params, {value: this.edittingText}));
                                this.edittingCellId = '';
                            }
                        }
                    });
                };
                return item;
            },
            surportHandle(item) {
                let options = item.options || [];
                let insideBtns = [];
                options.forEach(item => {
                    if (handleBtns[item]) insideBtns.push(handleBtns[item]);
                });
                let btns = item.button ? [].concat(insideBtns, item.button) : insideBtns;
                item.render = (h, params) => {
                    params.tableData = this.value;
                    return h('div', btns.map(item => item(h, params, this)));
                };
                return item;
            },
            handleColumns(columns) {
                this.insideColumns = columns.map((item, index) => {
                    let res = item;
                    if (res.editable) res = this.suportEdit(res, index);
                    if (res.key === 'handle') res = this.surportHandle(res);
                    return res;
                });
            },
            setDefaultSearchKey() {
                this.searchKey = this.columns[0].key !== 'handle' ?
                    this.columns[0].key : (this.columns.length > 1 ? this.columns[1].key : '');
            },
            handleClear(e) {
                if (e.target.value === '') this.insideTableData = this.value;
            },
            handleSearch() {
                if (this.searchKey === 'index') return;
                if (this.searchKey === 'selection') return;
                this.insideTableData = this.value.filter(item => {
                    return item[this.searchKey].indexOf(this.searchValue) > -1;
                });
            },
            handleTableData() {
                this.insideTableData = this.value.map((item, index) => {
                    let res = item;
                    res.initRowIndex = index;
                    return res;
                });
            },
            exportCsv(params) {
                this.$refs.tablesMain.exportCsv(params);
            },
            clearCurrentRow() {
                this.$refs.talbesMain.clearCurrentRow();
            },
            onCurrentChange(currentRow, oldCurrentRow) {
                this.$emit('on-current-change', currentRow, oldCurrentRow);
            },
            onSelect(selection, row) {
                this.$emit('on-select', selection, row);
            },
            onSelectCancel(selection, row) {
                this.$emit('on-select-cancel', selection, row);
            },
            onSelectAll(selection) {
                this.$emit('on-select-all', selection);
            },
            onSelectionChange(selection) {
                this.$emit('on-selection-change', selection);
            },
            onSortChange(column, key, order) {
                this.$emit('on-sort-change', column, key, order);
            },
            onFilterChange(row) {
                this.$emit('on-filter-change', row);
            },
            onRowClick(row, index) {
                this.$emit('on-row-click', row, index);
            },
            onRowDblclick(row, index) {
                this.$emit('on-row-dblclick', row, index);
            },
            onExpand(row, status) {
                this.$emit('on-expand', row, status);
            }
        },
        watch: {
            columns(columns) {
                this.handleColumns(columns);
                this.setDefaultSearchKey();
            },
            value(val) {
                this.handleTableData();
                this.handleSearch();
            }
        },
        mounted() {
            this.handleColumns(this.columns);
            this.setDefaultSearchKey();
            this.handleTableData();
        }
    };
</script>

<style lang="less">
    @import "./index";
</style>
